<?php
/**
 * 文件字段的值支持如下
 * 字符串 xcfs://xxx | fileServiceUrl/xxx
 * 一维数组 多个文件 ["xcfs://xxx" | "fileServiceUrl/xxx","xcfs://xxx" | "fileServiceUrl/xxx"]
 */

namespace Hilaoyu\LaravelExtend\Services\XcfsCient\Traits;

use Hilaoyu\LaravelExtend\Services\XcfsCient\XcfsClient;
use Hilaoyu\Utils\UtilStr;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;

trait ModelWithXcfsFilesTrait
{

    //设置普通文件字段 ['字段名1','字段名2']
    protected function modelWithXcfsFilesTraitSettingFileFields(): array
    {
        return [];
    }

    //设置需要清洗内容文件的字段 ['字段名1','字段名2']
    protected function modelWithXcfsFilesTraitSettingContentHasFileFields(): array
    {
        return [];
    }


    public function eventOnSavingModelWithXcfsFilesTrait()
    {
        $this->modelWithXcfsFilesTraitSetFieldValue();
    }


    private function modelWithXcfsFilesTraitGetFieldValue($field_name)
    {
        $value = data_get($this->attributes, $field_name);
        if ($this->hasCast($field_name)) {
            $value = $this->castAttribute($field_name, $value);
        }
        return $value;
    }

    private function modelWithXcfsFilesTraitSetFieldValue(){
        $uris = $this->modelWithXcfsFilesTraitGetUris();
        $xcfsClient = new XCfsClient();
        $data = $xcfsClient->verifyAndUse($uris);
        foreach ($this->modelWithXcfsFilesTraitSettingFileFields() as $field_name) {
            $value = $this->modelWithXcfsFilesTraitGetFieldValue($field_name);

            if (is_string($value)) {
                $value = Arr::exists($data,$value) ? $data[$value] : $value;

            } elseif (is_array($value)) {
                foreach ($value as $k => $v) {
                    $value[$k] = Arr::exists($data,$v) ? $data[$v] : $v;
                }
            }

            $this->attributes[$field_name] = $value;
        }

        foreach ($this->modelWithXcfsFilesTraitSettingContentHasFileFields() as $field_name) {
            $value = $this->modelWithXcfsFilesTraitGetFieldValue($field_name);
            //dump($key,$value);

            if (is_string($value)) {
                $value = UtilStr::replace($value,$data);
            } elseif (is_array($value)) {
                foreach ($value as $ck => $cv) {
                    $value[$ck] = UtilStr::replace($cv,$data);
                }
            }

            $this->attributes[$field_name] = $value;
        }
    }

    public function modelWithXcfsFilesTraitGetUris()
    {


        $uris = collect([]);

        foreach ($this->modelWithXcfsFilesTraitSettingFileFields() as $field_name) {
            $value = $this->modelWithXcfsFilesTraitGetFieldValue($field_name);

            if (is_string($value)) {
                $uris->push($value);

            } elseif (is_array($value)) {
                foreach ($value as  $v) {
                    $uris->push($v);
                }

            }


        }

        foreach ($this->modelWithXcfsFilesTraitSettingContentHasFileFields() as $field_name) {
            $value = $this->modelWithXcfsFilesTraitGetFieldValue($field_name);
            //dump($key,$value);

            if (is_string($value)) {
                $uris = $uris->merge(static::ParseContentUrls($value));
            } elseif (is_array($value)) {
                foreach ($value as $ck => $cv) {
                    $uris = $uris->merge(static::ParseContentUrls($cv));
                }
            }

            //$this->attributes[$key] = $value;
        }

        return $uris->all();

    }


    static public function ParseContentUrls($content)
    {
        $urls = [];

        preg_match_all(static::ContentUriPattern(), $content, $matches, PREG_SET_ORDER);
        foreach ($matches as $match) {
            $urls[] = $match[2];
        }

        return $urls;
    }




    public function eventOnConstructModelWithXcfsFilesTrait()
    {
        $this->append($this->modelWithXcfsFilesTraitGetAppends());
    }

    public function eventOnRetrievedModelWithXcfsFilesTrait()
    {
        $this->append($this->modelWithXcfsFilesTraitGetAppends());
    }

    private function modelWithXcfsFilesTraitGetAppends()
    {
        $appends = [];
        foreach ($this->modelWithXcfsFilesTraitSettingFileFields() as $field_name) {
            $appends[] = $field_name;
        }
        foreach ($this->modelWithXcfsFilesTraitSettingContentHasFileFields() as $field_name) {
            $appends[] = $field_name;
        }
        return $appends;
    }

    public function __call($method, $parameters)
    {
        $field_name = $this->modelWithXcfsFilesTraitMethodToAttributeKey($method);
        if($field_name && in_array($field_name,$this->modelWithXcfsFilesTraitSettingFileFields())){
            return$this->modelWithXcfsFilesTraitSetFiledViewValue($field_name);
        }
        if($field_name && in_array($field_name,$this->modelWithXcfsFilesTraitSettingContentHasFileFields())){
            return$this->modelWithXcfsFilesTraitSetContentViewValue($field_name);
        }

        return parent::__call($method, $parameters);
    }
    private function modelWithXcfsFilesTraitSetFiledViewValue($field_name)
    {
        $value = $this->modelWithXcfsFilesTraitGetFieldValue($field_name);

        if($value){
            if (is_string($value)) {
                $value = XcfsClient::SignResponseUrl($value);

            } elseif (is_array($value)) {
                foreach ($value as $k => $v) {
                    $value[$k] = XcfsClient::SignResponseUrl($v);
                }
            }

        }
        return $value;
    }
    private function modelWithXcfsFilesTraitSetContentViewValue($field_name)
    {
        $value = $this->modelWithXcfsFilesTraitGetFieldValue($field_name);

        if($value){
            if (is_string($value)) {
                $value = preg_replace_callback(static::ContentUriPattern(), function ($matches) {
                    return $matches[1] . XcfsClient::SignResponseUrl($matches[2]) . $matches[3];
                }, $value);

            } elseif (is_array($value)) {
                foreach ($value as $k => $v) {
                    $value[$k] = preg_replace_callback(static::ContentUriPattern(), function ($matches) {
                        return $matches[1] . XcfsClient::SignResponseUrl($matches[2]) . $matches[3];
                    },$v);
                }
            }

        }
        return $value;

    }

    private function modelWithXcfsFilesTraitMethodToAttributeKey($method)
    {
        $method = trim($method);
        if (Str::startsWith($method, 'get') && Str::endsWith($method, 'Attribute')) {
            $file_field = Str::snake(Str::substr(Str::substr($method, 0, Str::length($method) - 9), 3));

            if (in_array($file_field, $this->modelWithXcfsFilesTraitSettingFileFields()) || in_array($file_field, $this->modelWithXcfsFilesTraitSettingContentHasFileFields())) {

                return $file_field;
            }
        }
        return '';
    }

    static private function ContentUriPattern()
    {
        return "/([\s]+(?:src|href)[\s]*=[\s]*[\"'])(.*?)([\"'])/isS";
    }
}
